package rad.framework.seam;

import java.util.ArrayList;
import java.util.List;

import javax.faces.model.SelectItem;
import javax.persistence.Query;

import rad.framework.jsf.JsfUtil;
import rad.framework.jsf.ListCache;

import org.jboss.seam.core.Expressions.ValueExpression;

/**
 * Metadata for populating a combo or suggestion box.
 * 
 * @author boudyacho
 * 
 */
public class ComboBox<COMP, TGT, SRC> extends BaseReferenceQuery<COMP, TGT, SRC> {
	
	// TODO view 
	// - hyper-link by class/view?id + begin
	
	// http://www.jboss.org/file-access/default/members/jbossrichfaces/freezone/
	// docs/devguide/en/faq/faq.html#d0e579
	
	public ComboBox(Object component, String name) {
		super(component, name);
	}
	
	public ComboBox(Object component, String instanceName, String name) {
		super(component, instanceName, name);
	}
	
	// --------------------------------------
	
	public List<SelectItem> getItems() {
		ListCache cache = new ListCache() {
			protected Object proceed(Object ctx) {
				return format(query(null));
			}
		};
		return (List<SelectItem>) cache.invoke(null, getName());
	}

	public List<SelectItem> filter(final Object filter) {
		ListCache cache = new ListCache() {
			protected Object proceed(Object ctx) {
				return format(query((String)filter));
			}
		};
		return (List<SelectItem>) cache.invoke(null, getName());
	}
	
	// --------------------------------------

	public List query(String filter) {
		String eql = getEql();
		
		Query qry = getEntityManager().createQuery(eql);

		if (isFiltered()) {
			qry.setParameter(getFilterParamName(), getWildcardFilter(filter));
		}

		return qry.getResultList();
	}
	
	// --------------------------------------

	public List<SelectItem> format(List list) {
		ValueExpression valueExpression = getExpression(getItemValue());
		ValueExpression labelExpression = getExpression(getItemLabel());
		List<SelectItem> items = new ArrayList<SelectItem>(list.size());
		for (Object object : list) {
			JsfUtil.getRequestMap().put(getAlias(), object);
	         if (isFiltered()) {
	        	 Object label = labelExpression.getValue();
	        	 if (label == null) {
	        		 label = "";
	        	 }
		         items.add(new SelectItem(valueExpression.getValue(), label.toString()));
	         } else {
		         items.add(new SelectItem(object, labelExpression.getValue().toString()));
	         }
	         JsfUtil.getRequestMap().remove(getAlias());
		}
		return items;
	}

	public String getLabel(TGT object) {
		String label = null;
		if (object != null) {
			ValueExpression labelExpression = getExpression(getItemLabel());
			JsfUtil.getRequestMap().put(getAlias(), object);
			label = labelExpression.getValue().toString();
			JsfUtil.getRequestMap().remove(getAlias());
		}
		return label;
	}
	
	// --------------------------------------

	public ComboBox addRestriction(String restriction) {
		_addRestriction(restriction);
		return this;
	}
	
	// --------------------------------------

	public String getMinChars() {
		return "2";
	}

	public String getFrequency() {
		return "1";
	}

	// --------------------------------------

	public String getConverterId() {
		if ("entityManager".equals(getPersistenceContextName())) {
			return "org.jboss.seam.ui.EntityConverter";
		} else {
			return getPersistenceContextName() + "EntityConverter";
		}
		//"rad.framework.jsf.NaturalIdConverter";
	}

	public String getValidatorId() {
		return "rad.framework.jsf.IdValidator";
	}
}
